#include "user_include.h"
#define USART_MSG_NUM 3
#define USART_BUFFER_SIZE 200
#define USART_HANDLE huart1
#define USART_DMA_HANDLE hdma_usart1_rx
#define USART_DMA_TX_HANDLE hdma_usart1_tx

static osSemaphoreId_t sid_Semaphore;
static osMessageQueueId_t myQueueRxHandle;
static uint8_t usart_rx_table[USART_MSG_NUM][USART_BUFFER_SIZE];

static void user_init(void);
static void user_isr(void);
static void user_task(void);
static void user_tx_cpl_callback(void);
static uint8_t user_read(uint8_t *buffer, uint8_t *count);
static uint8_t user_write(uint8_t *buffer, uint8_t count);

struct driver_uart_struct_def driver_uart_struct = {
    .init = user_init,
    .isr = user_isr,
    .task = user_task,
    .tx_cpl_callback = user_tx_cpl_callback,
    .read = user_read,
    .write = user_write,
};

static void user_init(void)
{
    osTimerId_t timer_id;
    __HAL_UART_ENABLE_IT(&USART_HANDLE, UART_IT_IDLE);
    sid_Semaphore = osSemaphoreNew(1U, 1U, NULL);
    myQueueRxHandle = osMessageQueueNew(USART_MSG_NUM, 4, NULL);
    HAL_UART_Receive_DMA(&USART_HANDLE, usart_rx_table[0], USART_BUFFER_SIZE);
}
/****************************************************************************
 * name:user_read
 * function: block read function
 * in parameters : buffer:store table  count:buffer size
 * out parameters : no
 ****************************************************************************/
static uint8_t user_read(uint8_t *buffer, uint8_t *count)
{
    uint32_t value;
    osStatus_t temp;
    uint8_t *p;
    uint8_t ret;

    temp = osMessageQueueGet(myQueueRxHandle, &value, NULL, 0);
    if (temp == osOK)
    {

        taskENTER_CRITICAL();
        p = (uint8_t *)value;
        *count = p[USART_BUFFER_SIZE - 1];
        if (*count > USART_BUFFER_SIZE - 1)
        {
            *count = USART_BUFFER_SIZE - 1;
        }
        memcpy(buffer, p, *count);
        taskEXIT_CRITICAL();
        ret = 0;
    }
    else
    {
        ret = 1;
    }
    return ret;
}

/****************************************************************************
 * name:user_write
 * function: block usart write
 * in parameters : buffer : send table count send size
 * out parameters : no
 ****************************************************************************/
static uint8_t user_write(uint8_t *buffer, uint8_t count)
{
    if (count > USART_BUFFER_SIZE)
    {
        count = USART_BUFFER_SIZE;
    }
    HAL_UART_Transmit_DMA(&USART_HANDLE, buffer, count);
    osSemaphoreAcquire(sid_Semaphore, 100U);
    return 0;
}
/****************************************************************************
 * name:user_isr
 * function: usart isr function
 * in parameters : no
 * out parameters : no
 ****************************************************************************/
static void user_isr(void)
{
    static uint8_t count = 0;
    BaseType_t pxHigherPriorityTaskWoken;
    uint32_t p = 0;
    uint8_t dma_count = 0;
    uint8_t temp = 0;

    if (__HAL_UART_GET_FLAG(&USART_HANDLE, UART_FLAG_IDLE))
    {
        __HAL_UART_CLEAR_IDLEFLAG(&USART_HANDLE);
        dma_count = __HAL_DMA_GET_COUNTER(&USART_DMA_HANDLE);
        temp = USART_BUFFER_SIZE - dma_count;
        dma_count = temp;
        if (osMessageQueueGetCount(myQueueRxHandle) == USART_MSG_NUM)
        {
            osMessageQueueGet(myQueueRxHandle, &p, NULL, 0); // clear old data
        }
        HAL_UART_AbortReceive(&USART_HANDLE);
        p = (uint32_t)usart_rx_table[count];
        usart_rx_table[count][USART_BUFFER_SIZE - 2] = 0;
        usart_rx_table[count][USART_BUFFER_SIZE - 1] = dma_count;
        osMessageQueuePut(myQueueRxHandle, &p, NULL, 0);
        count++;
        if (count >= USART_MSG_NUM)
        {
            count = 0;
        }
        p = (uint32_t)usart_rx_table[count];
        HAL_UART_Receive_DMA(&USART_HANDLE, (uint8_t *)p, USART_BUFFER_SIZE);
    }
}
/****************************************************************************
 * name:XferCpltCallback
 * function: dma send complete callback function
 * in parameters : hdma
 * out parameters : no
 ****************************************************************************/
static void user_tx_cpl_callback(void)
{
    osSemaphoreRelease(sid_Semaphore);
}
static void user_task(void)
{
    uint8_t buffer[128];
    uint8_t buffer1[128];
    uint8_t count = 0;
    uint8_t ret = 0;
    driver_uart_struct.init();
    while (1)
    {
        ret = driver_uart_struct.read(buffer, &count);
        if (ret == 0)
        {
            // driver_uart_struct.write(buffer, count);
            driver_uart_struct.write("hello world 1234567890\r\n", strlen("hello world 1234567890\r\n"));
        }
    }
}
